Video is generally stored as a collection of compressed streams in a container file. Each stream may be video images, an audio track, or other data (such as subtitles), synchronized with each other. The container (file format) determines how those streams are stored. IDLffVideoWrite supports a number of file formats, including:
IDLffVideoWrite attempts to guess the intended file format from the filename, if one isn't explicitly specified using the FORMAT keyword in the IDLffVideoWrite::Init method.
In the following example, you can change the extension of the filename to try the different formats.
PRO VIDEO_EXAMPLE_FILE_FORMAT
width = 500
height = 500
fps = 20
surf = SURFACE(/TEST, /BUFFER, DIMENSIONS=[width,height])
; Each of the following lines produces a file in
; a different format.
oVid = IDLffVideoWrite('video_example_file_format.webm')
;oVid = IDLffVideoWrite('video_example_file_format.gif')
;oVid = IDLffVideoWrite('video_example_file_format.swf')
;oVid = IDLffVideoWrite('video_example_file_format.bin', FORMAT='mp4')
; Prints out a list of supported file formats
PRINT, "Supported file formats: ", oVid.GetFormats()
vidStream = oVid.AddVideoStream(width, height, fps)
FOR i = 0, 90 do begin
surf.Rotate, 4, /YAXIS
frame = surf.CopyWindow()
!NULL = oVid.Put(vidStream, frame)
ENDFOR
oVid.Cleanup
END
There are many different ways to compress each of these formats. A codec (short for COder/DECoder) is software for compressing and decompressing a stream. Each format's support for different audio and video codecs vary. If the codecs aren't explicitly set, IDLffVideoWrite will try to choose a default appropriate for the file format. Some common video codecs are: MPEG-2 Video, MPEG-4 Visual, and H.264.
Some common audio codecs are AAC, MP3, FLAC, and PCM. Some codecs are better than others, some are more widely supported than others, and some have strengths and weaknesses that make them best suited for specific purposes.
In general, which codec you use plays a big role in file size and quality, but the choice of file format matters little so long as it supports your chosen codecs, and is supported by the player software.
Each file format supports a different set of codecs for its streams. In general, we suggest using MP4 or AVI files with MPEG-4 compressed video. The following example makes an AVI file using the default bitrates and codecs: 2 Mbps MPEG-4 video, and 128 Kbps MP2 audio.
; A helper function to create the audio
FUNCTION create_audio, offset, length, scale
t = (lindgen(length) + offset*length) / scale
s = (t/(2^7) OR t OR t/(2^6)) * 10 + 4 * (t AND t/(2^13) or t/(2^6))
RETURN, FIX(s, type=1) * (2^5)
END
; Now create the video
PRO VIDEO_EXAMPLE_DEFAULT_SETTING
width = 500
height = 500
fps = 20
sampleRate = 44100
surf = SURFACE(/TEST, /BUFFER, DIMENSIONS=[width,height])
oVid = IDLffVideoWrite('video_example_default_setting.avi')
vidStream = oVid.AddVideoStream(width, height, fps)
audStream = oVid.AddAudioStream(sampleRate)
for i = 0, 100 do begin
surf.Rotate, 4, /YAXIS
audio = create_audio(i, sampleRate/fps, 5)
frame = surf.CopyWindow()
!NULL = oVid.Put(audStream, audio)
!NULL = oVid.Put(vidStream, frame)
ENDFOR
oVid.Cleanup
END
You can explicitly set the codec used to compress audio and video. For example, you might prefer the msmpeg4v2
codec over standard mpeg4
, because Windows Media Player in certain versions of Windows can play msmpeg4v2 video but not mpeg4.
You can also set what bitrate the codec should attempt to compress down to, in bits per second. In general, quality and file size are directly proportional to bitrate. Bitrate simply sets a goal for the codec; actual results may be higher or lower. Different codecs respond to adjusted bitrates differently; you may need to experiment to find the right tradeoff for your application.
The following example prints the supported audio and video codecs, then sets the codec and bitrate.
PRO VIDEO_EXAMPLE_CUSTOM_SETTING
width = 500
height = 500
fps = 20
surf = SURFACE(/TEST, /BUFFER, DIMENSIONS=[width,height])
oVid = IDLffVideoWrite('video_example_custom_setting.avi')
; Prints out a list of supported file formats
PRINT, "Supported audio codecs: ", oVid.GetCodecs(/AUDIO)
PRINT, "Supported video codecs: ", oVid.GetCodecs(/VIDEO)
; Uses the msmpeg4v2 codec, rather than the default mpeg4.
; Also, sets a very low bitrate of 800Kbps to show how file
; size is reduced and quality suffers. Try comparing with
; a fairly high setting of 8Mbps- 8e6.
vidStream = oVid.AddVideoStream(width, height, fps, $
CODEC='msmpeg4', BIT_RATE=8e5)
FOR i = 0, 90 DO BEGIN
surf.Rotate, 4, /YAXIS
frame = surf.CopyWindow()
!NULL = oVid.Put(vidStream, frame)
ENDFOR
oVid.Cleanup
END
It is also possible to output audio-only files, shown in the following example:
; A helper function to create the audio
FUNCTION make_music, offset, length, scale
t = (lindgen(length) + offset*length) / scale
s = (t/(2^7) OR t OR t/(2^6)) * 10 + 4 * (t AND t/(2^13) or t/(2^6))
return, fix(s, type=1) * (2^5)
end
; Now create the audio file
PRO audio_example
sampleRate = 44100
oVid = IDLffVideoWrite('audio_example.wav')
audStream = oVid.AddAudioStream(sampleRate)
FOR i = 0, 60 DO BEGIN
audio = make_music(i, sampleRate, 5)
!NULL = oVid.Put(audStream, audio)
ENDFOR
oVid.Cleanup
END
If you have trouble playing videos, we recommend using VLC Media Player (http://www.videolan.org/). It is free, open-source, available for virtually every operating system, and can play nearly any type of video.
IDLffVideoWrite uses the open-source FFmpeg library to handle video file formats and compression. FFmpeg supports many file formats, audio codecs, and video codecs, but copyright and patent concerns prevent us from being able to include some of these features in the version that comes with IDL.
However, we have designed IDLffVideoWrite so that you can replace the default version of FFmpeg in IDL with a different one. If you wish to replace IDL's version of FFmpeg with another one, see the following section.
Some reasons you might want to replace the FFmpeg version include: being able to put audio in MP4 files with the AAC audio codec, putting MP3-compressed audio in AVI files or by itself into an MP3 file, using the Apple Quicktime (*.mov) file format, and using the H.264 video codec.
To replace the IDL version of FFmpeg, the following files need to be to replaced. They are located in IDL_DIR\bin\bin.x86
(for 32-bit IDL)or
IDL_DIR\bin\bin.x86_64
(for 64-bit IDL).
Because building FFmpeg for Windoes can be difficult, there are web sites that maintain builds of the latest versions. To locate one of these, try searching for something like "ffmpeg-0.8-win32-shared."
Please make copies of the .dll files before replacing them. Instructions on how to build FFmpeg for Linux and Mac OS are also available on various online sites. As with Windows, just the four FFmpeg library files in the appropriate IDL bin directory need to be replaced to upgrade.
You can check if your replacement was successful by printing out the values of IDLffVideoWrite::GetCodecs() and ::GetFormats() before and after — the lists of supported codecs and formats should become much longer after you replace the files.
H.264 is widely supported and one of the best video codecs today. If you have replaced IDL's version of FFmpeg with one that includes H.264, you can use it by specifying the 'libx264' codec when adding the video stream. We recommend using an MP4 container format, because AVI does not support H.264 and is likely to have problems. When adding an H.264 stream to a video, you can use the PRESET keyword to select one of the built-in groups of settings for the H.264 compression.
See IDLffVideoWrite for the full list of presets. Most of them (with names such as 'ultrafast', 'medium', 'slower', etc.) simply adjust the tradeoff between encoding speed and video quality, with fairly constant file size. The 'lossless' presets will guarantee perfect video quality, each with a different tradeoff between encoding speed and file size. Not all players that support H.264 can play lossless video.
The following example uses a replaced FFmpeg version and specifies the 'libx264' codec:
; A helper function to create the audio
FUNCTION audio_helper, offset, length, scale
t = (lindgen(length) + offset*length) / scale
s = (t/(2^7) OR t OR t/(2^6)) * 10 + 4 * (t AND t/(2^13) or t/(2^6))
RETURN, FIX(s, type=1) * (2^5)
END
; Now create the video
PRO video_example_custom_ffmpeg
width = 500
height = 500
fps = 20
sampleRate = 44100
surf = surface(/TEST, /BUFFER, DIMENSIONS=[width,height])
oVid = IDLffVideoWrite('video_example_custom_ffmpeg.mp4')
vidStream = oVid.AddVideoStream(width, height, fps, $
CODEC='libx264', PRESET='medium')
audStream = oVid.AddAudioStream(sampleRate, CODEC='aac')
FOR i = 0, 200 DO BEGIN
surf.Rotate, 4, /YAXIS
audio = audio_helper(i, sampleRate/fps, 5)
frame = surf.CopyWindow()
!NULL = oVid.Put(audStream, audio)
!NULL = oVid.Put(vidStream, frame)
ENDFOR
oVid.Cleanup
END
For more information, see IDLffVideoWrite.